#include "glwidget.h"

#include <QDebug>

GLWidget::GLWidget(VIEWPORT_TYPE type, QWidget *parent) :
    QGLWidget(parent)
{
    m_type = type;
    m_scene = NULL;
    this->resize(600,600);
    xRot = 0;
    yRot = 0;
    zRot = 0;
    m_position.x = 0.0f;
    m_position.y = 0.0f;
    m_position.z = 5.0f;
    m_camera_speed = 1.0f;
}

void GLWidget::setXRotation(int angle)
{
    normalizeAngle(&angle);
    if (angle != xRot) {
        xRot = angle;
        emit xRotationChanged(angle);
        updateGL();
    }
}

void GLWidget::setYRotation(int angle)
{
    normalizeAngle(&angle);
    if (angle != yRot) {
        yRot = angle;
        emit yRotationChanged(angle);
        updateGL();
    }
}

void GLWidget::setZRotation(int angle)
{
    normalizeAngle(&angle);
    if (angle != zRot) {
        zRot = angle;
        emit zRotationChanged(angle);
        updateGL();
    }
}

void GLWidget::normalizeAngle(int *angle)
{
    while (*angle < 0)
        *angle += 360 * 16;
    while (*angle > 360 * 16)
        *angle -= 360 * 16;
}

void GLWidget::mousePressEvent(QMouseEvent *event)
{
    lastPos = event->pos();
    this->setFocus();
}

void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
    int dx = event->x() - lastPos.x();
    int dy = event->y() - lastPos.y();

    if (event->buttons() & Qt::LeftButton) {
        setXRotation(xRot + 8 * dy);
        setYRotation(yRot + 8 * dx);
    } else if (event->buttons() & Qt::RightButton) {
        setXRotation(xRot + 8 * dy);
        setZRotation(zRot + 8 * dx);
    }
    lastPos = event->pos();
}

void GLWidget::keyPressEvent(QKeyEvent *event){    
    if(event->key()==Qt::Key_A){
        m_position.x -= m_camera_speed;
    }
    if(event->key()==Qt::Key_D){
        m_position.x += m_camera_speed;
    }
    if(event->key()==Qt::Key_S){
        m_position.z += m_camera_speed;
    }
    if(event->key()==Qt::Key_W){
        m_position.z -= m_camera_speed;
    }
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(m_position.x, m_position.y, m_position.z, m_position.x, m_position.y, -m_position.z, 0.0,1.0,0.0);
    updateGL();
}


void GLWidget::initializeGL(){
//    if(glewInit()){
//        return;
//    }
    glClearColor(0.5f,0.5f,0.5f,0.5f);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glViewport(0,0,this->width(),this->height());
    float aspect_ratio = (float)this->width()/(float)this->height();
    gluPerspective(45.0,aspect_ratio,0.01,100.0);
    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glDepthFunc		(GL_LEQUAL);
    glEnable		(GL_DEPTH_TEST);    

    //m_shaders.setShaders("vertex_default.glsl","fragment_default.glsl");
    //m_shaders.bindProgram();

    switch(m_type){
    case TOP_VIEW:
        gluLookAt(0.0f,3.0f,0.0f,
                  0.0f,-1.0f,0.0f,
                  0.0f,0.0f,1.0f);
        break;
    case BOTTOM_VIEW:
        gluLookAt(0.0f,-3.0f,0.0f,
                  0.0f,1.0f,0.0f,
                  0.0f,0.0f,1.0f);
        break;
    case FRONT_VIEW:
        gluLookAt(0.0f,0.0f,5.0f,
                  0.0f,0.0f,-1.0f,
                  0.0f,1.0f,0.0f);
        break;
    case BACK_VIEW:
        gluLookAt(0.0f,0.0f,-3.0f,
                  0.0f,0.0f,1.0f,
                  0.0f,1.0f,0.0f);
        break;

    }
}

void GLWidget::paintGL(){

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glPushMatrix();
    glRotated(xRot / 16.0, 1.0, 0.0, 0.0);
    glRotated(yRot / 16.0, 0.0, 1.0, 0.0);
    glRotated(zRot / 16.0, 0.0, 0.0, 1.0);

    renderer.render_scene(m_scene);

    glPopMatrix();

}

void GLWidget::resizeGL(int width, int height){
    glViewport(0,0,width,height);
    float aspect_ratio = (float)width/(float)height;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0,aspect_ratio,0.01,100.0);
    glMatrixMode(GL_MODELVIEW);
}

void GLWidget::set_scene(Scene *scene){
    m_scene = scene;
}
